import axios from 'axios'
import TimeUtils from "@/utils/TimeUtils"
import StringUtils from "@/utils/StringUtils"
import Cfg from "@/config/Cfg"
import CryptoJS from 'crypto-js'
import UserSessionService from "@/service/UserSessionService"

const RestClient = {
    request(url, method, headers, data, callback, failCallback, timeout) {
        timeout = timeout || 30000
        let param = {
            url: url,
            timeout: timeout,
            method: method,
            headers: headers
        };
        if (data) {
            if (typeof data === 'object' || typeof data === 'array') {
                param.data = JSON.stringify(data)
            } else {
                param.data = data
            }
        }

        let instance = axios.create(param);
        instance.interceptors.request.use(null, function (error) {
            if (failCallback) {
                failCallback(error)
            }
            return Promise.reject(error)
        });

        instance.interceptors.response.use(function (response) {
            console.log('response: ', response)
            if (callback) {
                let responseData = response.data;
                if (typeof responseData === 'string') {
                    if (StringUtils.isBlank(responseData)) {
                        responseData = "{}";
                    }
                    try {
                        responseData = JSON.parse(responseData)
                    } catch (e) {
                        console.error(e)
                    }
                }
                callback(responseData)
            }
            return response
        }, function (error) {
            console.log('request error: ', error)

            let { data, statusResponse, statusText } = error
            console.log('ss:', data, statusResponse, statusText)

            let msg = {}
            if (!error.response) {
                // 请求无响应
                if (failCallback) {
                    failCallback({
                        status: 502,
                        message: '请求超时，请重试！',
                        code: 'NOT_CONNECTED'
                    })
                }
                return Promise.reject(error)
            }

            let status = error.response.status
            if (typeof error.response.data === 'object') {
                msg = error.response.data
            } else {
                msg.code = 'UNKNOWN ERROR'
                msg.message = error.response.data
            }

            msg.status = status
            if (failCallback) {
                failCallback(msg)
            }
            return Promise.reject(error)
        })
        //param = {...param, ...exCfg};
        console.log('param:', param)
        return instance.request(param)
    },

    _header(uri, method, data) {
        let bodyStr = ''
        if (typeof data === 'object' || typeof data === 'array') {
            const keys = Object.keys(data)
            keys.sort()
            keys.forEach(key => {
                bodyStr += `${bodyStr==='' ? '' : '&'}${key}=${data[key]}`
            })
        }
        const nonce = TimeUtils.formatDate(new Date(), 'yyyyMMddhhmmss') + StringUtils.getRandomString(6)
        const signContent = `${uri}\n${method}\n${bodyStr}\n${nonce}\n${Cfg.api_access_key}`
        //console.log('signContent:', signContent)
        const sign = CryptoJS.SHA256(signContent).toString().toUpperCase()
        const authorization = `ForFun token=${Cfg.api_access_token};nonce=${nonce};sign=${sign};`
        return {
            'Content-Type': 'application/json;charset=UTF-8',
            'Authorization': authorization
        }
    },

    _formatUri(uri, query) {
        if (StringUtils.isBlank(uri)) {
            uri = '/'
        }
        if (!query) {
            return uri
        }
        const keys = Object.keys(query)
        keys.sort()
        let queryStr = ''
        keys.forEach(key => {
            queryStr += `${queryStr==='' ? '' : '&'}${key}=${query[key]}`
        })
        if (uri.indexOf('?') > -1) {
            return `${uri}&${queryStr}`
        } else {
            return `${uri}?${queryStr}`
        }
    },

    _formatUrl (uri) {
        return `${Cfg.server_addr}${uri}`
    },

    _formatUserToken(headers, call) {
        UserSessionService.getToken((token) => {
            if (token) {
                headers['F-Token'] = token
            }
            call(headers)
        })
    },

    get(uri, callback, failCallback, timeout, query) {
        uri = this._formatUri(uri, query)
        const url = this._formatUrl(uri)
        const method = 'GET'
        const headers = this._header(uri, method)
        this._formatUserToken(headers, (headers)=> {
            this.request(url, method, headers, null, callback, failCallback, timeout)
        })
    },

    post(uri, data, callback, failCallback, timeout, query) {
        uri = this._formatUri(uri, query)
        const url = this._formatUrl(uri)
        const method = 'POST'
        const headers = this._header(uri, method, data)
        this._formatUserToken(headers, (headers)=> {
            this.request(url, method, headers, data, callback, failCallback, timeout)
        })
    },

    put(uri, data, callback, failCallback, timeout, query) {
        uri = this._formatUri(uri, query)
        const url = this._formatUrl(uri)
        const method = 'PUT'
        const headers = this._header(uri, method, data)
        this._formatUserToken(headers, (headers)=> {
            this.request(url, method, headers, data, callback, failCallback, timeout)
        })
    },

    delete(uri, callback, failCallback, timeout, query) {
        uri = this._formatUri(uri, query)
        const url = this._formatUrl(uri)
        const method = 'DELETE'
        const headers = this._header(uri, method)
        this._formatUserToken(headers, (headers)=> {
            this.request(url, method, headers, null, callback, failCallback, timeout)
        })
    }
}

export  default  RestClient